package com.fei.myback.common;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Iterator;

/**
 * 权限访问控制
 */
@Component
@Slf4j
public class RoleContro implements AccessDecisionManager {
    /**
     * 判断是否有权限
     *
     * @param authentication   包含了UserDetails用户信息
     * @param object           包含了request请求信息
     * @param configAttributes 由CustomFilterInvocationSecurityMetadataSource.getAttributes(object)返回的请求的资源（url）所需要的权限（角色）集合
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        /**
         * 如果请求的资源不需要权限，则直接放行
         */
        log.info("[资源权限]: {}", configAttributes);
        log.info("[用户权限]: {}", authentication.getAuthorities());
        /**
         * 判断用户所拥有的权限是否是资源所需要的权限之一，如果是则放行，否则拦截
         */
        Iterator<ConfigAttribute> it = configAttributes.iterator();
        while (it.hasNext()) {
            // 资源的权限
            ConfigAttribute resourceAttr = it.next();
            String resourceRole = resourceAttr.getAttribute();

            // 用户的权限
            for (GrantedAuthority userAuth : authentication.getAuthorities()) {
                log.info("[资源角色==用户角色] ？ {} == {}", resourceRole.trim(), userAuth.getAuthority().trim());
                if (resourceRole.trim().equals(userAuth.getAuthority().trim())) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("权限不足");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
